package dac.dao;

import dac.MD5;
import dac.model.Usuario;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.servlet.http.HttpSession;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

public class UsuarioDAO {
    private Connection con;
    private HttpSession session;
    
    public UsuarioDAO (Connection con) {
        this.con = con;
    }
    
    public UsuarioDAO (Connection con, HttpSession session) {
        this.con = con;
        this.session = session;
    }
    
    public void setSession (HttpSession session) {
        this.session = session;
    }
    
    public String login (String email, String senha) throws SQLException {
        
        String query = "SELECT * FROM usuario WHERE";
              query += " email='" + email + "'";
              query += " AND senha=MD5('" + senha + "')"; // Senha ja em MD5
              
        PreparedStatement st = con.prepareStatement(query);
        ResultSet rs = st.executeQuery();
        
        if (rs.next()) {
            atualizaBeanSession(Integer.parseInt(rs.getString("id")));
            
            switch (Integer.parseInt(rs.getString("nivel_acesso"))) {
                case 1:
                    return "cliente";
                case 2:
                    return "admin";
                default:
                    return "false";   
            }
        }
        
        return "false";
        
    }
    
    public List<Usuario> listarTodos() throws SQLException {
        List<Usuario> resultado = new ArrayList<Usuario>();
        
        PreparedStatement st = con.prepareStatement("SELECT * FROM usuario");
        ResultSet rs = st.executeQuery();
        
        while (rs.next()) {
            Usuario u = new Usuario();
            u.setId( Integer.parseInt(rs.getString("id")) );
            u.setNome(rs.getString("nome"));
            u.setEmail(rs.getString("email"));
            u.setTelefone(rs.getString("telefone"));
            u.setEndereco(rs.getString("endereco"));
            u.setSenha(rs.getString("senha"));            
            u.setNivel_acesso( Integer.parseInt(rs.getString("nivel_acesso")) );
            
            resultado.add(u);
        }
        
        return resultado;
    }
    
    
    /*
    * Lista todos os usuario em JSON
    */
    public String listarTodosJSON() throws SQLException {   
        String query = "SELECT * FROM usuario";
        
        PreparedStatement st = con.prepareStatement(query);
        ResultSet rs = st.executeQuery();        
        
        JSONArray jsonArray = new JSONArray();
        
        while (rs.next()) {
            JSONObject jsonObject = new JSONObject();
            
            jsonObject.put("id", Integer.parseInt(rs.getString("id")) );
            jsonObject.put("nome", rs.getString("nome") );
            jsonObject.put("email", rs.getString("email") );
            jsonObject.put("telefone", rs.getString("telefone") );
            jsonObject.put("endereco", rs.getString("endereco") );
            
            jsonArray.add(jsonObject);
        }
        
        if ( jsonArray.isEmpty() ){
            return "false";
        }
        return jsonArray.toString();
    }
    
    
    
    /*
    * Lista todos os usuario em JSON
    */
    public String listarUmJSON(String id) throws SQLException {   
        String query = "SELECT * FROM usuario WHERE id="+id;
        
        PreparedStatement st = con.prepareStatement(query);
        ResultSet rs = st.executeQuery();        
        
        JSONArray jsonArray = new JSONArray();
        
        while (rs.next()) {
            JSONObject jsonObject = new JSONObject();
            
            jsonObject.put("id", Integer.parseInt(rs.getString("id")) );
            jsonObject.put("nome", rs.getString("nome") );
            jsonObject.put("email", rs.getString("email") );
            jsonObject.put("telefone", rs.getString("telefone") );
            jsonObject.put("endereco", rs.getString("endereco") );
            
            jsonArray.add(jsonObject);
        }
        
        if ( jsonArray.isEmpty() ){
            return "false";
        }
        return jsonArray.toString();
    }
    
    
    /*
     * --
     */
    public String cadastroUsuario (Map params) throws SQLException {
        return cadastroUsuario(params, 1); // Cliente
    }
    
    public String cadastroUsuario (Map params, int nivel_acesso) throws SQLException {
        Iterator i = params.keySet().iterator();
        String[] possivel = new String[]{
                "nome", "email", "telefone", "endereco", "senha"
        };
        String SQLValues = "",
               SQLFields = "",
               login = "", senha = "";
        
        boolean loginafter = false;
        
        while ( i.hasNext() ) {
            String key = (String) i.next();
            String value = ((String[]) params.get( key ))[ 0 ];
            
            if( key.equals("loginafter") && value.equals("true") ) {
                loginafter = true;
            }
            
            // Area de Admin passa como parametro o nivel de acesso
            if( key.equals("nivel_acesso") ) { nivel_acesso = Integer.parseInt(value); }
            
            if( Arrays.asList(possivel).contains(key) ) {
                
                // Para fazer o login apos o cadastro (se for requisitado o login)
                if( key.equals("email") ) { login = value; }
                if( key.equals("senha") ) { senha = value; }
                
                if( !key.equals("senha") ) {
                    SQLFields += key + ",";
                    SQLValues += "'" + value + "',";
                } else {
                    // E senha, entao tem que ser MD5
                    SQLFields += key + ",";
                    SQLValues += "MD5('" + value + "'),";
                }
            }
        }
        // Remove a ultima ','
        SQLFields = SQLFields.substring(0, SQLFields.length()-1);
        SQLValues = SQLValues.substring(0, SQLValues.length()-1);
        
        // nivel acesso 2=admin, 1=cliente  
        String query = "INSERT INTO usuario (nivel_acesso,"+SQLFields+") ";
              query += "VALUES ('"+nivel_acesso+"',"+SQLValues+")";
              
        PreparedStatement st = con.prepareStatement(query);
        int rs = st.executeUpdate();
        
        if (rs==1) {
            if (loginafter) { return login(login, senha); }
            return "true";
        }
        
        return "false";
    }
    
    
    /*
    * Editar Usuario
    */
    public String editarUsuario (Map params) throws SQLException {
        return editarUsuario(params, 1); // Cliente (default)
    }
    
    public String editarUsuario (Map params, int nivel_acesso) throws SQLException {
        Iterator i = params.keySet().iterator();
        String[] possivel = new String[]{
                "nome", "email", "telefone", "endereco", "senha", "nivel_acesso"
        };
        String SQL = "";
        int u_id=0;
        
        
        while ( i.hasNext() ) {
            String key = (String) i.next();
            String value = ((String[]) params.get( key ))[ 0 ];
            
            // Area de Admin passa como parametro o nivel de acesso
            if( key.equals("id") ) { u_id = Integer.parseInt(value); }
            
            // E um campo valido e nao vazio (caso nao altere a senha)
            if( Arrays.asList(possivel).contains(key) && !value.isEmpty() ) {
                                
                if( !key.equals("senha") ) {
                    SQL += key + "='" + value + "',";
                } else {
                    // E senha, entao tem que ser MD5
                    SQL += key + "=MD5('" + value + "'),";
                    
                }
            }
        }
        // Remove a ultima ','
        SQL = SQL.substring(0, SQL.length()-1);
        
        String query = "UPDATE usuario SET "+SQL+" WHERE id="+u_id;
        
              
        PreparedStatement st = con.prepareStatement(query);
        int rs = st.executeUpdate();
        
        if (rs==1) {
            return "true";
        }
        
        return "false";
    }
    
    
    /*
     * Metodo que faz a atulizacao dos dados do usuario no banco de dados
     */
    public boolean atualizaUsuario (String SQLValues) throws SQLException {
        Usuario u = (Usuario) session.getAttribute("u");
        String query = "UPDATE usuario SET "+SQLValues+" WHERE id="+u.getId();
              
        PreparedStatement st = con.prepareStatement(query);
        int rs = st.executeUpdate();
        
        if (rs==1) {
            
            atualizaBeanSession(u.getId());
            return true;
        }
        
        return false;
    }
    
    
    /*
     * Metodo que cria/atualiza a bean do usuario na sessao
     * usada quando efetuada um login/atualizacao de configuracao
     */
    private void atualizaBeanSession (int usuarioId) throws SQLException {
        String query = "SELECT * FROM usuario WHERE id="+usuarioId;
        
        PreparedStatement st = con.prepareStatement(query);
        ResultSet rs = st.executeQuery();
        
        if (rs.next()) {
            Usuario u = new Usuario();
            u.setId( Integer.parseInt(rs.getString("id")) );
            u.setNome(rs.getString("nome"));
            u.setEmail(rs.getString("email"));
            u.setTelefone(rs.getString("telefone"));
            u.setEndereco(rs.getString("endereco"));
            u.setSenha(rs.getString("senha"));            
            u.setNivel_acesso( Integer.parseInt(rs.getString("nivel_acesso")) );

            this.session.setAttribute("u", u);            
        }
    }
    
    
    /*
     * Metodo que faz uma consulta de determinado campo
     * usado no cadastro de usuarios para nao duplicar email/cpf
     */
    public String consultaValidaCadastro (String campo, String valor) throws SQLException {
        
        PreparedStatement st = con.prepareStatement("SELECT "+campo+" FROM usuario WHERE "+campo+"='"+valor+"'");
        ResultSet rs = st.executeQuery();
        
        if (rs.next()) {
            return "false"; // Existe
        }
        
        return "true"; // Nao existe
    }
    
    
    /*
     * Procura por um usuario e retorna uma String (JSON) do seu cadastro
     * caso nao exista retorna vazio
     */
    public String pesquisaCliente (String nome) throws SQLException {
        PreparedStatement st = con.prepareStatement("SELECT * FROM usuario WHERE nome LIKE '%"+nome+"%'");
        ResultSet rs = st.executeQuery();
        
        JSONArray jsonArray = new JSONArray();
        
        while (rs.next()) {
            JSONObject jsonObject = new JSONObject();
            
            jsonObject.put("id", Integer.parseInt(rs.getString("id")) );
            jsonObject.put("nome", rs.getString("nome") );
            jsonObject.put("email", rs.getString("email") );
            jsonObject.put("telefone", rs.getString("telefone") );
            jsonObject.put("endereco", rs.getString("endereco") );
            jsonObject.put("senha", rs.getString("senha") );
            jsonObject.put("nivel_acesso", Integer.parseInt(rs.getString("nivel_acesso")) );
            
            jsonArray.add(jsonObject);
        }
        
        if ( jsonArray.isEmpty() ){
            return "false";
        }
        return jsonArray.toString();
       
    }
    
    
    public String removerCliente(String id) throws SQLException{
        PreparedStatement st = con.prepareStatement("DELETE FROM usuario WHERE id="+id);
        int rs = st.executeUpdate();
        
        if (rs==1) {
            return "true"; // Removido
        }
        
        return "false"; // Erro
    }
}